package cn.tedu.s1.controller;

import cn.tedu.s1.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Controller
public class UserController {
    private static File userDir;

    static {
        userDir = new File("users");
        if (!userDir.exists()) {
            userDir.mkdirs();
        }
    }

    /*
        总结404情况:
        1:点击超链接直接404.或者业务处理完毕后重定向浏览器发生404.
        这一类请求页面出现404的情况都是因为target/classes/static下没有对应的页面文件。
        如果src/main/resources下有对应的文件，那么有可能是IDEA编译时出现的bug，导致没有复制过去。
        解决办法:
        1.1:在IDEA上方菜单栏依次选取:Build->rebuild project 重新编译一遍项目。
        1.2:手动将resources下的页面文件复制到target下对应的位置上。


        2:在注册，登录这类提交表单的页面上，点击按钮提交表单后发生404.
          原因:表单上action的值和UserController上对应业务方法上的@RequestMapping中指定的参数路径不一致。
          注意:这两个路径都应当使用“/”开始！例如:atcion="/myweb/reg"，不要使用action="myweb/reg"

        点击按钮提交表单后出现404，如何区分是处理业务后重定向没有找到页面引起，还是没有找到对应的业务方法引起
        区别在于:查看地址栏上的路径。
        如果路径还是提交表单时的路径，则说明该404引起原因是上述第二个原因(没有找到处理业务方法)。
        如果路径已经改变为重定向指定的请求某个页面。则说明该404引起原因是上上述第一种原因。


        关于HttpServletResponse中的重定向方法sendRedirect():
        同一个响应对象只能调用一次该方法。否则会抛出异常。因此如果我们在做注册或登录时，由于用户输入信息有误等操作
        希望重定向到一个页面后，一定保证该处理方法后续不会再走到一个重定向的调用。通常可以用return结束方法。

     */
    @RequestMapping("/myweb/login")
    /*
        由于login.html页面上表单里只有两个输入框，分别是username,password
        因此这里User对象中应当也仅有username,password有值。
     */
    public void login(User user, HttpServletResponse response) {
        System.out.println(user);
        File userFile = new File(userDir, user.getUsername() + ".obj");
        if (userFile.exists()) {//该用户存在
            //反序列化该文件得到该注册用户信息进行密码比对
            try (
                    ObjectInputStream ois = new ObjectInputStream(
                            new FileInputStream(userFile)
                    );
            ) {
                User user1 = (User) ois.readObject();//user1表示的是注册用户信息
                if (user1.getPassword().equals(user.getPassword())) {
                    //密码对了，登录成功
                    response.sendRedirect("/myweb/login_success.html");
                    return;
                }
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        try {
            response.sendRedirect("/myweb/login_fail.html");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @RequestMapping("/myweb/showAllUser")
    public void showAllUser(HttpServletResponse response) {
     /*
        解决动态页面乱码问题:
        在调用response.getWriter()之前设置好ContentType并且指定字符集即可。
        操作如下:
        response.setContentType("text/html;charset=utf-8");
        PrintWriter pw = response.getWriter();//这句话要在setContentType()之后调用
     */
        //1将users目录下的所有obj文件进行反序列化，得到所有的注册用户
        List<User> userList = new ArrayList<>();
        //1.1获取users目录下的所有obj文件(文件过滤器)
        //1.2遍历每一个obj文件并利用对象输入流进行反序列化
        //1.3将反序列化的对象存入userList备用
        File[] users = userDir.listFiles(f -> f.getName().endsWith(".obj"));
        for (File userFile : users) {
            try (
                    ObjectInputStream ois = new ObjectInputStream(
                            new FileInputStream(
                                    userFile
                            )
                    )
            ) {
                User user = (User) ois.readObject();
                userList.add(user);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        /*
            2生成一个HTML页面(动态页面)并包含所有用户数据
         */
        //添加响应头，用于将来告知浏览器该动态数据是一个html页面
        response.setContentType("text/html;charset=utf-8");//添加后半部分的字符集设定避免页面乱码
        try {
            PrintWriter pw = response.getWriter();
            pw.println("<!DOCTYPE html>");
            pw.println("<html lang=\"en\">");
            pw.println("<head>");
            pw.println("<meta charset=\"UTF-8\">");
            pw.println("<title>用户列表</title>");
            pw.println("</head>");
            pw.println("<body>");
            pw.println("<center>");
            pw.println("<h1>用户列表</h1>");
            pw.println("<table border=\"1\">");
            pw.println("<tr>");
            pw.println("<td>用户名</td>");
            pw.println("<td>密码</td>");
            pw.println("<td>昵称</td>");
            pw.println("<td>年龄</td>");
            pw.println("</tr>");
            for (User user : userList) {
                pw.println("<tr>");
                pw.println("<td>" + user.getUsername() + "</td>");
                pw.println("<td>" + user.getPassword() + "</td>");
                pw.println("<td>" + user.getNickname() + "</td>");
                pw.println("<td>" + user.getAge() + "</td>");
                pw.println("</tr>");
            }
            pw.println("</table>");
            pw.println("</center>");
            pw.println("</body>");
            pw.println("</html>");
        } catch (IOException e) {
            e.printStackTrace();
        }


    }


    /*
            我们使用一个对象作为参数时
            首先:spring会用User的【无参构造器】实例化User实例
            并将form表单中每个输入框的名字去寻找User中对应属性的set方法，将该输入框的值调用对应属性的set方法
            将值设置到user对象该属性上。
            例如:
            reg.html页面上表单里有4个输入框，名字分别是username,password,nickname,age
            此时spring实例化User对象后，就会分别调用setUsername(),setPassword(),setNickname(),setAge()将
            这四个输入框的值设置到User对象的这四个属性上。

            【因此注意:User对象上定义的属性名必须和页面表单上对应输入框的名字一致且这些属性都提供了get set方法。那么
            spring才会做上述操作!!!!】
    */
    @RequestMapping("/myweb/reg")
    public void reg(User user, HttpServletResponse response) {
        System.out.println(user);
        File userFile = new File(userDir, user.getUsername() + ".obj");
        try (
                ObjectOutputStream oos = new ObjectOutputStream(
                        new FileOutputStream(userFile)
                )
        ) {
            oos.writeObject(user);//不是userFile对象！！！！！！！！！！！！！！！！
            response.sendRedirect("/myweb/reg_success.html");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


//  还支持直接把表单输入框的名字作为参数定义在这里，那么此时调用该方法时会spring会自动对应并将表单数据传入对应参数
//    public void reg(String username,String password,String nickname,int age, HttpServletResponse response){
//        System.out.println(username+","+password+","+nickname+","+age);
//        User user = new User(username,password,nickname,age);
//
//        File userFile = new File(userDir,username+".obj");
//        try (
//                ObjectOutputStream oos = new ObjectOutputStream(
//                        new FileOutputStream(userFile)
//                )
//        ){
//            oos.writeObject(user);//不是userFile对象！！！！！！！！！！！！！！！！
//            response.sendRedirect("/myweb/reg_success.html");
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }


//    WebServer里处理业务方法的传参形式。spring也支持
//    public void reg(HttpServletRequest request, HttpServletResponse response){
//        String username = request.getParameter("username");
//        String password = request.getParameter("password");
//        String nickname = request.getParameter("nickname");
//        String ageStr = request.getParameter("age");
//        int age = Integer.parseInt(ageStr);
//        System.out.println(username+","+password+","+nickname+","+age);
//        User user = new User(username,password,nickname,age);
//
//        File userFile = new File(userDir,username+".obj");
//        try (
//                ObjectOutputStream oos = new ObjectOutputStream(
//                        new FileOutputStream(userFile)
//                )
//        ){
//            oos.writeObject(user);//不是userFile对象！！！！！！！！！！！！！！！！
//            response.sendRedirect("/myweb/reg_success.html");
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//
//
//    }
}










